type Constructor<T = {}> = new (...args: ESObject[]) => T;

/**
 * 声明合并补充类型定义
 */
declare global {
  interface Object {
    /**
     * 在一个局部作用域内引入变量
     */
    let<T, R>(this: T, block: (it: T) => R): R;

    /*
      apply<T>(this: T, block: () => void): T;
    */
    /**
     * 对一个对象的属性进行设置
     */
    apply<T>(this: T, block: (thiz: T) => void): T;

    /**
     * 对一个对象进行一些附加处理
     */
    also<T>(this: T, block: (it: T) => void): T;
  }
}

/**
 * 装饰器工厂函数
 */
export function ScopeFunctions() {
  return function<T extends Constructor>(target: T) {

    // 添加 let 方法
    target.prototype.let = function<T, R>(this: T, block: (it: T) => R): R {
      return block(this);
    };

    /*
      target.prototype.apply = function<T>(this: T, block: () => void): T {
        block.bind(this);
        return this;
      };
    */
    // 添加 apply 方法
    target.prototype.apply = function<T>(this: T, block: (thiz: T) => void): T {
      block(this);
      return this;
    };

    // 添加 also 方法
    target.prototype.also = function<T>(this: T, block: (it: T) => void): T {
      block(this);
      return this;
    };

    return class extends target {};
  };
}